#ifndef BUILDER_H
#define BUILDER_H

#include <iostream>

class Door {};
class Wall {};
class Maze {
public:
  virtual Door* CreateDoor(int r1, int r2) = 0;
  virtual Wall* CreateWall(int n) = 0;
};

class SchoolDoor : public Door {
public:
  SchoolDoor(int r1, int r2) {
    std::cout << "SchoolDoor : " << r1 << " -> " << r2 << std::endl;
  }
};

class SchoolWall : public Wall {
public:
  SchoolWall(int n) {
    std::cout << "SchoolWall : " << n << std::endl;
  }
};

class CastleDoor : public Door {
public:
  CastleDoor(int r1, int r2) {
    std::cout << "CastleDoor : " << r1 << " -> " << r2 << std::endl;
  }
};

class CastleWall : public Wall {
public:
  CastleWall(int n) {
    std::cout << "CastleWall : " << n << std::endl;
  }
};

class CastleMaze : public Maze {
public:
  virtual Door* CreateDoor(int r1, int r2) {
    return new CastleDoor(r1, r2);
  }

  virtual Wall* CreateWall(int n) {
    return new CastleWall(n);
  }
};

class SchoolMaze : public Maze {
public:
  virtual Door* CreateDoor(int r1, int r2) {
    return new SchoolDoor(r1, r2);
  }

  virtual Wall* CreateWall(int n) {
    return new SchoolWall(n);
  }
};

class Builder {
public:
  virtual void BuildDoor(int r1, int r2) = 0;
  virtual void BuildWall(int n) = 0;
  virtual void BuildMaze() = 0;
  virtual Maze* GetMaze() = 0;
};

class CastleBuilder {
public:
  virtual void BuildDoor(int r1, int r2) {
    current_maze_->CreateDoor(r1, r2);
  }

  virtual void BuildWall(int n) {
    current_maze_->CreateWall(n);
  }

  virtual void BuildMaze() {
    current_maze_ = new CastleMaze();
  }

  virtual Maze* GetMaze() {
    return current_maze_;
  }
private:
  Maze* current_maze_;
};

class SchoolBuilder {
public:
  virtual void BuildDoor(int r1, int r2) {
    current_maze_->CreateDoor(r1, r2);
  }

  virtual void BuildWall(int n) {
    current_maze_->CreateWall(n);
  }

  virtual void BuildMaze() {
    current_maze_ = new SchoolMaze();
  }

  virtual Maze* GetMaze() {
    return current_maze_;
  }
private:
  Maze* current_maze_;
};

#endif // BUILDER_H
